package api

import (
	"fmt"
	"github.com/gin-contrib/sessions"
	"github.com/gin-gonic/gin"
	"github.com/objcoding/wxpay"
	"github.com/skip2/go-qrcode"
	"github.com/smartwalle/alipay/v2"
	"net/http"
	"strconv"
	"time"
	. "xm_shop/database"
	. "xm_shop/models"
	. "xm_shop/utils"
)

type BuyController struct{}

// 去结算页面数据
func (b BuyController) Checkout(context *gin.Context) {
	var cartList []Cart
	Cookie.Get(context, "cartList", &cartList)
	// 订单切片
	var orderList []Cart
	// 统计总价格
	var allPrice float64
	// 统计总数量
	var allNum int
	for i := 0; i < len(cartList); i++ {
		if cartList[i].Checked {
			allPrice += cartList[i].Price * float64(cartList[i].Num)
			orderList = append(orderList, cartList[i])
			allNum += orderList[i].Num
		}
	}
	// 判断orderList的长度
	if len(orderList) == 0 {
		context.String(http.StatusBadRequest, "没有选择商品")
		return
	}
	// 获取当前用户的收货地址
	var user User
	Cookie.Get(context, "userInfo", &user)
	var addressList []Address
	DB.Where("uid = ?", user.ID).Order("id desc").Find(&addressList)

	// 生成签名
	orderSign := Md5(GetRandomNum())
	session := sessions.Default(context) // 获取session
	session.Set("orderSign", orderSign)
	session.Save()
	context.JSON(http.StatusOK, gin.H{
		"allPrice":    allPrice,
		"orderList":   orderList,
		"allNum":      allNum,
		"addressList": addressList,
		"orderSign":   orderSign,
	})
}

// 去支付接口(生成订单)
func (b BuyController) Buy(context *gin.Context) {
	// 0. 防止重复提交
	orderSign := context.PostForm("order_sign")
	session := sessions.Default(context)
	sessionOrderSign := session.Get("orderSign")
	orderSignStr, ok := sessionOrderSign.(string)
	if !ok {
		context.String(http.StatusBadRequest, "签名过期")
		return
	}
	if orderSignStr != orderSign {
		context.String(http.StatusBadRequest, "签名不匹配")
		return
	}
	// 删除session中的相关数据
	session.Delete("orderSign")
	session.Save()
	// 1. 获取用户信息
	var user User
	Cookie.Get(context, "userInfo", &user)
	// 2. 获取默认地址
	var address Address
	DB.Where("uid = ? AND default_address = ?", user.ID, 1).Take(&address)
	// 判断是否存在默认收货地址
	if address.ID == 0 {
		context.String(http.StatusBadRequest, "不存在默认收货地址")
		return
	}
	// 3. 获取购买商品的信息
	var cartList []Cart
	Cookie.Get(context, "cartList", &cartList)
	var orderList []Cart
	var allPrice float64
	for i := 0; i < len(cartList); i++ {
		if cartList[i].Checked {
			allPrice += cartList[i].Price * float64(cartList[i].Num)
			orderList = append(orderList, cartList[i])
		}
	}

	// 4. 把订单信息放在订单表, 把商品信息放在订单详细表
	order := Order{
		OrderID:     GetOrderNo(),
		Uid:         user.ID,
		AllPrice:    allPrice,
		Phone:       address.Phone,
		Address:     address.Address,
		Name:        address.Name,
		PayStatus:   0,
		PayType:     0,
		OrderStatus: 0,
		AddTime:     int(time.Now().UnixNano()),
	}
	if err1 := DB.Create(&order).Error; err1 != nil {
		context.String(http.StatusBadRequest, "订单创建失败")
		return
	}
	// 遍历创建订单详细
	for i := 0; i < len(orderList); i++ {
		orderItem := OrderItem{
			OrderId:      order.ID,
			Uid:          user.ID,
			ProductTitle: orderList[i].Title,
			ProductId:    orderList[i].ID,
			ProductImg:   orderList[i].GoodsImg,
			ProductPrice: orderList[i].Price,
			ProductNum:   orderList[i].Num,
			GoodsVersion: orderList[i].GoodsVersion,
			GoodsColor:   orderList[i].GoodsColor,
			AddTime:      int(time.Now().Unix()),
		}
		if err1 := DB.Create(&orderItem).Error; err1 != nil {
			context.String(http.StatusBadRequest, "订单详细创建失败")
			return
		}
	}
	// 5. 删除购物车中选中的数据
	var noSelectCartList []Cart
	for i := 0; i < len(cartList); i++ {
		if !cartList[i].Checked {
			noSelectCartList = append(noSelectCartList, cartList[i])
		}
	}
	cartList = noSelectCartList
	Cookie.Set(context, "cartList", cartList) // 保存到cookie

	context.String(http.StatusOK, "订单创建成功")
}

// 去支付页面数据
func (b BuyController) Pay(context *gin.Context) {
	orderId, err1 := strconv.Atoi(context.Query("order_id"))
	if err1 != nil {
		context.String(http.StatusBadRequest, "参数有误")
		return
	}
	// 获取当前用户
	var user User
	Cookie.Get(context, "userInfo", &user)
	var order Order
	// 检索订单
	DB.Where("id = ? AND uid = ?", orderId, user.ID).Take(&order)
	if order.ID == 0 {
		context.String(http.StatusBadRequest, "订单不存在")
		return
	}
	// 获得订单对应的商品
	var orderItems []OrderItem
	DB.Where("order_id = ?", orderId).Find(&orderItems)
	context.JSON(http.StatusOK, gin.H{
		"orderItems": orderItems,
		"order":      order,
	})
}

// 支付宝支付接口
func (b BuyController) AliPay(context *gin.Context) {
	var aliPublicKey = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsVWdZR+KgNdejCJTec2PlPvPlDJLhSLZl1tfU775zFVSuljCa2dXs4SWf5mlwgXqIdOPMwyJ3UhXYyyb0V1L/Gn2rFTt5VJ61HeLhRzRQETqYU0gB6+89EPwBTisGmVEm3M6yH4IXth7MqjF0pWWhIgLwcQBdxAaaK7GPmb+ox/2fQPwJAw6Wi8QqWzRtwf7iGgiQEJ0SqWHRuaa16xqx71AaX3p53twfHjhNpKcCewCWQKzg/7ETZLAWnQX0Qkrjgs694vwBYQf51GkWeq0DKMHsnmkZ5e3oJGzClfCEh7mdXhL9ywvmtgOZ46UCHx2tH1N5smmYvfcpgLJrL/AxQIDAQAB"
	var privateKey = "MIIEowIBAAKCAQEApVU7UEqG/c4dVn2ge5DAO+1OdxclEsqlYPBKmpjaGBJKmhUV/og/bx98tG0ugQhHlVMZT759SEqGhjVjpMMLLd60zHXq3DPb9pKhiGb79rZBDly8GryfnbihdnATvDhRXSi+wcmhKlkbQi1Oj7PLOPQ6CPPuOTTqsJQQ3eFiRt6D2KvmFR+CYZMSSFB+ESluCvUGRONzIZ7mV3ZJT7zpqehzwgcCoG1jkvzHhnC8kS1q6bMgHBhl2LhttQJYSQaYemuNXNgfv3Zpi2HJQqHxJffopGGw/OQN/380vnHBApSo9RFSOEExvm/Ucw4NZR5bDi3/+vXnfYPNPWnLz71StQIDAQABAoIBAQCB7mmev/M2ozULM89bTHbGoch4bwgDrJ4rgKwgst8y660VSlzum8S+X9BxOxzA6vDWuWe688khdvAhqPOWGHJAqjUMOd9JDrhfHv0zZTu+t5yI3Pg3SuVl3iOGIK5hzSCkRdEkGoE99qklaNXEuVeMeuLhBlLBQoTuIG7g8K97YT9gm/KXzE+DgApWxXkHzoXL0sdIRsJIUV/OFlRIiZqP66vm2A9cL7PNn9A+Wu5/rV+wZPypOgagwDQZzxbK3XwW4px/UvT4pfWgaCjkG7HyIj8tWLaOvpqnbhyFOg0cyC+y7sZmG2OWCEUWAZ5N+gmXlLCrtH+ppMPpX3mdZ+5BAoGBAN+XBohEoJt1b5ox8ivY0NxyMV1EN4xB/Su7Gmc9ug3zKqnednPX4kuJOMwVWn3ghtRD+5Uz3Jwi/i5zuwN5ULp3G6rsHWZFAry/EcxG3YuCoGkiyUxcQLVKQn8NDYt+paEIukyHWFtf3WA0TuDGCWEplhm6mdAgWkgpzEWnA2M3AoGBAL1MZ8vIY6rM4uc7v1iYiX2BGhdpa1oxhvecfMu6ioRsq4SbkoPd8OO43ihN9ad0d/0CvcKqP4bF/yxvyVs0If2QUkDo5gu7XypXQi8GZq7k2hOCbk2vuQLJtjVl4wtU6AzMdPU0XC8difgH/5IFeOesS9Rvahx2gnGuXA7NqMdzAoGASfRdP8NbUDBGyrzMej5Lzy6iL1Q5/1VwVP+dGxrqqGSO7wLbMTPt8MghljdV6B7U2e7mjxJJXQeiBWFYMSz2S8bLyvwwOTyITD/ythuWeeeqATx1UqGM8anvVrDNkx8/z4TggiGeUxLhWUnT8TrvrUihEj+LUrDwy7+vhjZYw38CgYB+lQkTi/yZykgwuBNL+zR1aE86OJRAy72k9k+9LBBUXRaUpjNjWpYqsQRdj0QlpgxWc+7QrWeth9kKrfXHtyTDmi5mmVa7oaARgCgRqgYgDYiGY0G/UTI2WwwsyOT6PtytMktDbK/4EZig8zhDPMWMpfpPI/Gg9t5jhmSowX2LYQKBgDl0ONzV/vm9k0MmTEj5aZYnKfyuLwG55t1Sf0POhxEbUKI5aontuyllG8OmjyXass5AX7Kvc1XCSS/fXTozGSIkLEOzJXL1qAmMI6XEEs3chVULbhX4DQ5Dp/a3KROKBiIZCdqBD4lZgpTC81yUegjqy5IJvuLxmppELppj0l0f"
	var appId = "9021000135692195"
	//最后一个参数 false 表示沙箱环境 true 表示正式环境
	client, _ := alipay.New(appId, aliPublicKey, privateKey, false)
	var p = alipay.TradePagePay{}                           // 电脑支付调用这个函数
	p.NotifyURL = "http://127.0.0.1:8000/default/v2/notify" // 这里要是线上地址
	p.ReturnURL = "http://127.0.0.1:8000/default/v2/return"
	p.Subject = "这是一个 Gin 订单"
	template := "2006-01-02 15:04:05"
	p.OutTradeNo = time.Now().Format(template)
	p.TotalAmount = "0.1"
	p.ProductCode = "FAST_INSTANT_TRADE_PAY" // 电脑网站支付的固定写法
	var url, err4 = client.TradePagePay(p)
	if err4 != nil {
		fmt.Println(err4)
	}
	var payURL = url.String()
	fmt.Println(payURL)
	context.String(http.StatusOK, payURL)
}

// 异步回调接口(POST) 必须在这里处理订单完成支付的逻辑
func (b BuyController) AlipayNotify(context *gin.Context) {
	fmt.Println("这里的异步回调接口")
	var aliPublicKey = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsVWdZR+KgNdejCJTec2PlPvPlDJLhSLZl1tfU775zFVSuljCa2dXs4SWf5mlwgXqIdOPMwyJ3UhXYyyb0V1L/Gn2rFTt5VJ61HeLhRzRQETqYU0gB6+89EPwBTisGmVEm3M6yH4IXth7MqjF0pWWhIgLwcQBdxAaaK7GPmb+ox/2fQPwJAw6Wi8QqWzRtwf7iGgiQEJ0SqWHRuaa16xqx71AaX3p53twfHjhNpKcCewCWQKzg/7ETZLAWnQX0Qkrjgs694vwBYQf51GkWeq0DKMHsnmkZ5e3oJGzClfCEh7mdXhL9ywvmtgOZ46UCHx2tH1N5smmYvfcpgLJrL/AxQIDAQAB"
	var privateKey = "MIIEowIBAAKCAQEApVU7UEqG/c4dVn2ge5DAO+1OdxclEsqlYPBKmpjaGBJKmhUV/og/bx98tG0ugQhHlVMZT759SEqGhjVjpMMLLd60zHXq3DPb9pKhiGb79rZBDly8GryfnbihdnATvDhRXSi+wcmhKlkbQi1Oj7PLOPQ6CPPuOTTqsJQQ3eFiRt6D2KvmFR+CYZMSSFB+ESluCvUGRONzIZ7mV3ZJT7zpqehzwgcCoG1jkvzHhnC8kS1q6bMgHBhl2LhttQJYSQaYemuNXNgfv3Zpi2HJQqHxJffopGGw/OQN/380vnHBApSo9RFSOEExvm/Ucw4NZR5bDi3/+vXnfYPNPWnLz71StQIDAQABAoIBAQCB7mmev/M2ozULM89bTHbGoch4bwgDrJ4rgKwgst8y660VSlzum8S+X9BxOxzA6vDWuWe688khdvAhqPOWGHJAqjUMOd9JDrhfHv0zZTu+t5yI3Pg3SuVl3iOGIK5hzSCkRdEkGoE99qklaNXEuVeMeuLhBlLBQoTuIG7g8K97YT9gm/KXzE+DgApWxXkHzoXL0sdIRsJIUV/OFlRIiZqP66vm2A9cL7PNn9A+Wu5/rV+wZPypOgagwDQZzxbK3XwW4px/UvT4pfWgaCjkG7HyIj8tWLaOvpqnbhyFOg0cyC+y7sZmG2OWCEUWAZ5N+gmXlLCrtH+ppMPpX3mdZ+5BAoGBAN+XBohEoJt1b5ox8ivY0NxyMV1EN4xB/Su7Gmc9ug3zKqnednPX4kuJOMwVWn3ghtRD+5Uz3Jwi/i5zuwN5ULp3G6rsHWZFAry/EcxG3YuCoGkiyUxcQLVKQn8NDYt+paEIukyHWFtf3WA0TuDGCWEplhm6mdAgWkgpzEWnA2M3AoGBAL1MZ8vIY6rM4uc7v1iYiX2BGhdpa1oxhvecfMu6ioRsq4SbkoPd8OO43ihN9ad0d/0CvcKqP4bF/yxvyVs0If2QUkDo5gu7XypXQi8GZq7k2hOCbk2vuQLJtjVl4wtU6AzMdPU0XC8difgH/5IFeOesS9Rvahx2gnGuXA7NqMdzAoGASfRdP8NbUDBGyrzMej5Lzy6iL1Q5/1VwVP+dGxrqqGSO7wLbMTPt8MghljdV6B7U2e7mjxJJXQeiBWFYMSz2S8bLyvwwOTyITD/ythuWeeeqATx1UqGM8anvVrDNkx8/z4TggiGeUxLhWUnT8TrvrUihEj+LUrDwy7+vhjZYw38CgYB+lQkTi/yZykgwuBNL+zR1aE86OJRAy72k9k+9LBBUXRaUpjNjWpYqsQRdj0QlpgxWc+7QrWeth9kKrfXHtyTDmi5mmVa7oaARgCgRqgYgDYiGY0G/UTI2WwwsyOT6PtytMktDbK/4EZig8zhDPMWMpfpPI/Gg9t5jhmSowX2LYQKBgDl0ONzV/vm9k0MmTEj5aZYnKfyuLwG55t1Sf0POhxEbUKI5aontuyllG8OmjyXass5AX7Kvc1XCSS/fXTozGSIkLEOzJXL1qAmMI6XEEs3chVULbhX4DQ5Dp/a3KROKBiIZCdqBD4lZgpTC81yUegjqy5IJvuLxmppELppj0l0f"
	var appId = "9021000135692195"
	var client, err1 = alipay.New(appId, aliPublicKey, privateKey, true)
	if err1 != nil {
		fmt.Println(err1)
		return
	}
	context.Request.ParseForm()                        // 解析form表单的数据, 并且存放在Form变量中(这个是原始的做法, gin框架中已经帮你封装好了)
	ok, err := client.VerifySign(context.Request.Form) // 获取form表单解析的数据
	fmt.Println(ok, err)
	fmt.Println(context.Request.Form)
	context.String(200, "ok")
}

// 同步回调接口(GET)
func (b BuyController) AlipayReturn(context *gin.Context) {
	fmt.Println("这里是同步回调接口")
}

// 微信支付接口
func (b BuyController) WxPay(context *gin.Context) {
	// 1. 配置基本信息
	account := wxpay.NewAccount(
		"wx7bf3787c783116e4",               // appid
		"1502539541",                       // mchid
		"zhongyuantengitying6666666666666", // apikey
		false,                              // 是否为沙箱环境
	)
	client := wxpay.NewClient(account) // 创建微信支付客户端对象
	// 2.获取ip地址  订单号等信息
	ip := context.ClientIP()
	tradeNo := time.Now().Format("20060102150405")
	// 3. 统一调用下单
	params := make(wxpay.Params)
	params.SetString("body", "test"). // 标题
						SetString("out_trade_no", tradeNo).                            // 订单号
						SetInt64("total_fee", 1).                                      // 总费用
						SetString("spbill_create_ip", ip).                             // 客户端ip
						SetString("notify_url", "http://notify.objcoding.com/notify"). // 异步回调(线上地址)(需要和微信支付平台中设置的一致)
						SetString("trade_type", "NATIVE")                              // 网址支付需要改为NATIVE
	p, _ := client.UnifiedOrder(params) // p是一个map, 获取code_url, 用来生成二维码
	// 生成二维码
	png, err1 := qrcode.Encode(p["code_url"], qrcode.Medium, 256)
	if err1 != nil {
		context.String(http.StatusBadRequest, "生成二维码失败")
		return
	}
	context.JSON(http.StatusOK, gin.H{
		"result": p, // p中有个code_url字段, 这个字段拿来生成二维码, 默认过期时间2小时
		"png":    string(png),
	})
}

// 微信支付回调接口(异步)(POST)
func (b BuyController) WxPayNotify(context *gin.Context) {
	//1、获取表单传过来的 xml 数据
	xmlByte, _ := context.GetRawData() // 获取到的原始数据(请求体中的数据)
	xmlStr := string(xmlByte)

	postParams := wxpay.XmlToMap(xmlStr)
	fmt.Println(postParams)
	//2、校验签名
	account := wxpay.NewAccount(
		"wx7bf3787c783116e4",
		"1502539541",
		"zhongyuantengitying6666666666666",
		false,
	)
	client := wxpay.NewClient(account)
	isValidate := client.ValidSign(postParams) // 检验数据(支付成功为true)
	fmt.Println(isValidate)
	//3、更新订单
	context.String(200, "ok")
}

// 轮询获取订单状态
func (b BuyController) OrderPayStatus(context *gin.Context) {
	id, err1 := strconv.Atoi(context.Param("id"))
	if err1 != nil {
		context.String(http.StatusBadRequest, "参数有误")
		return
	}
	// 获取用户信息
	var user User
	Cookie.Get(context, "userInfo", &user)
	// 获取订单信息
	var order Order
	DB.Where("id = ? AND uid  = ?", id, user.ID).Take(&order)
	if order.ID == 0 {
		context.String(http.StatusBadRequest, "订单不存在")
		return
	}
	if order.PayStatus == 1 && order.OrderStatus == 1 { // 判断订单状态
		context.JSON(http.StatusOK, gin.H{
			"success": true,
		})
	}
	context.JSON(http.StatusOK, gin.H{
		"success": false,
	})
}
